---
layout: example
category: example
title: Create a timeline animation
description: Drag the range slider to visualize earthquakes that were greater than 5.9 magnitude in 2015.
---
<style>
.map-overlay {
    font: 12px/20px 'Helvetica Neue', Arial, Helvetica, sans-serif;
    position: absolute;
    width: 25%;
    top: 0;
    left: 0;
    padding: 10px;
}

.map-overlay .map-overlay-inner {
    background-color: #fff;
    box-shadow:0 1px 2px rgba(0, 0, 0, 0.20);
    border-radius: 3px;
    padding: 10px;
    margin-bottom: 10px;
}

.map-overlay h2 {
    line-height: 24px;
    display: block;
    margin: 0 0 10px;
}

.map-overlay .legend .bar {
    height: 10px;
    display: inline-block;
}

.map-overlay input {
    background-color: transparent;
    display: inline-block;
    width: 100%;
    position: relative;
    margin: 0;
    cursor: ew-resize;
}
</style>

<div id='map'></div>

<div class='map-overlay top'>
    <div class='map-overlay-inner'>
        <h2>Significant earthquakes in 2015</h2>
        <label id='month'></label>
        <input id='slider' type='range' min='0' max='11' step='1' value='0' />
    </div>
    <div class='map-overlay-inner'>
        <div id='legend' class='legend'>
            <div>Magnitude (m)</div>
        </div>
    </div>
</div>

<script src='//d3js.org/d3.v3.min.js' charset='utf-8'></script>
<script>
var map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/light-v8',
    center: [31.4606, 20.7927],
    zoom: 0.5
});

var popup = new mapboxgl.Popup({
    closeOnClick: false,
    closeButton: false
});

var legend = document.getElementById('legend');
var monthLabel = document.getElementById('month');

// Will contain the layers we wish to interact with on
// during map mouseover and click events.
var layerIDs = [];

var magnitudes = [
    [8, '#7F3121'],
    [7.75, '#913C23'],
    [7.5, '#A24724'],
    [7.25, '#B35424'],
    [7, '#C46222'],
    [6.75, '#D37120'],
    [6.5, '#E2801B'],
    [6.25, '#EF9014'],
    [6, '#FCA107']
];

var months = [
    'January',
    'February',
    'March',
    'April',
    'May',
    'June',
    'July',
    'August',
    'September',
    'October',
    'November',
    'December'
];

function filterBy(month, mag, index) {
    // Clear the popup if displayed.
    popup.remove();

    var filters = [
        "all",
        ["==", "month", month],
        [">=", "mag", mag[0]]
    ];

    if (index !== 0) filters.push(["<", "mag", magnitudes[index - 1][0]]);
    map.setFilter('circle-' + index, filters);
    map.setFilter('label-' + index, filters);

    // Set the label to the month
    monthLabel.textContent = months[month];
}

map.on('load', function() {

    // Data courtesy of http://earthquake.usgs.gov/
    // Query for significant earthquakes in 2015 URL request looked like this:
    // http://earthquake.usgs.gov/fdsnws/event/1/query
    //    ?format=geojson
    //    &starttime=2015-01-01
    //    &endtime=2015-12-31
    //    &minmagnitude=6'
    //
    // Here we're using d3 to help us make the ajax request but you can use
    // Any request method (library or otherwise) you wish.
    d3.json('{{site.baseurl}}/assets/data/significant-earthquakes-2015.geojson', function(err, data) {

        // Create a month property value based on time
        // used to filter against.
        data.features = data.features.map(function(d) {
            d.properties.month = new Date(d.properties.time).getMonth();
            return d;
        })

        map.addSource('earthquakes', {
            'type': 'geojson',
            'data': data
        });

        // Apply layer styles
        magnitudes.forEach(function(mag, i) {
            var layerID = 'circle-' + i;
            layerIDs.push(layerID);

            map.addLayer({
                "id": layerID,
                "interactive": true,
                "type": "circle",
                "source": "earthquakes",
                "paint": {
                    "circle-color": mag[1],
                    "circle-opacity": 0.75,
                    "circle-radius": (mag[0] - 4) * 10 // Nice radius value
                }
            });

            map.addLayer({
                "id": "label-" + i,
                "type": "symbol",
                "source": "earthquakes",
                "layout": {
                    "text-field": "{mag}m",
                    "text-font": ["Open Sans Bold", "Arial Unicode MS Bold"],
                    "text-size": 12
                },
                "paint": {
                    "text-color": "rgba(0,0,0,0.5)"
                }
            });

            // Set filter to first month of the year +
            // Magnitude rating. 0 = January
            filterBy(0, mag, i);

            // Add legend bar
            var bar = document.createElement('div');
            bar.className = 'bar';
            bar.title = mag[0];
            bar.style.width = 100 / magnitudes.length + '%';
            bar.style.backgroundColor = mag[1];
            legend.insertBefore(bar, legend.firstChild);
        });

        document.getElementById('slider').addEventListener('input', function(e) {
            var month = parseInt(e.target.value, 10);
            magnitudes.forEach(function(mag, i) {
                filterBy(month, mag, i);
            });
        });

        map.on('mousemove', function(e) {
            var features = map.queryRenderedFeatures(e.point, { layers: layerIDs });
            // Change the cursor style as a UI indicator.
            map.getCanvas().style.cursor = (features.length) ? 'pointer' : '';
        });

        map.on('click', function(e) {
            var features = map.queryRenderedFeatures(e.point, { layers: layerIDs });
            if (!features.length) {
                popup.remove();
                return;
            }

            var feature = features[0];

            var link = document.createElement('a');
            link.href = feature.properties.url;
            link.target = '_blank';
            link.textContent = feature.properties.place;

            // Use wrapped coordinates to ensure longitude is within (180, -180)
            var coords = feature.geometry.coordinates;
            var ll = new mapboxgl.LngLat(coords[0], coords[1]);
            var wrapped = ll.wrap();

            // Center the map to its point.
            map.flyTo({ center: wrapped });
            popup.setLngLat(wrapped)
                .setHTML(link.outerHTML)
                .addTo(map);
        });
    });
});
</script>
